//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-10-18 15:25
 */
//========================================================================

#ifndef _ASYNCHIO_H_
#define _ASYNCHIO_H_
#include "Pre.h"

#include "InetAddr.h"
#include "GlobalMacros.h"

// Forward declarations
class Proactor;
class TimeValue;
class MessageBlock;
class AsynchHandler;
class AsynchOptImpl;
class AsynchResultImpl;

/**
 * @class AsynchResult
 *
 * @brief An interface base class which allows users access to common
 * information related to an asynchronous operation.
 *
 * An interface base class from which you can obtain some basic
 * information like the number of bytes transferred.
 */
class AsynchResult
{
public:
    // Number of bytes transferred by the operation.
    size_t bytes_transferred (void) const;

    // Did the operation succeed?
    int success (void) const;

    /**
     * This is the ACT associated with the handle on which the
     * Asynch_Operation takes place.
     * On WIN32, this returns the ACT associated with the handle when it
     * was registered with the I/O completion port.
     *
     * @@ This is not implemented for POSIX4 platforms. Returns 0.
     */
    const void *completion_key (void) const;

    // Error value if the operation fails.
    int error (void) const;

    /**
     * On WIN32, this returns the event associated with the OVERLAPPED
     * structure.
     * This returns NDK_INVALID_HANDLE on POSIX4-Unix platforms.
     */
    NDK_HANDLE event (void) const;

    // This really makes sense only when doing file I/O.
    long long offset (void) const;

    // Destructor.
    virtual ~AsynchResult (void);
protected:
    // Constructor. This implementation will not be deleted.  The
    // implementation will be deleted by the Proactor.
    AsynchResult (AsynchResultImpl *implementation);

    // Get the implementation class.
    AsynchResultImpl *implementation (void) const;

    // Implementation class.
    AsynchResultImpl *implementation_;
};
// ---------------------------------------------------------------------
/**
 * @class AsynchOpt
 * @brief This is an interface base class for all asynch
 * operations. The resposiblility of this class is to forward
 * all methods to its delegation/implementation class, e.g.,
 * WIN32AsynchOpt or EpollAsynchOpt.
 *
 * There are some attributes and functionality which is common
 * to all asychronous operations. The delegation classes of this
 * class will factor out this code.
 */
class AsynchOpt
{
public:
    /**
     * Initializes the factory with information which will be used with
     * each asynchronous call.  If ({handle} == NDK_INVALID_HANDLE),
     * {AsynchHandler::handle} will be called on the {handler} to get the
     * correct handle.
     */
    int open (const AsynchHandler *handler,
	    NDK_HANDLE handle,
	    const void *completion_key,
	    Proactor *proactor);
    
    /**
     * (Attempts to) cancel the asynchronous operation pending against
     * the {handle} registered with this Operation.
     *
     * All completion notifications for the I/O operations will occur
     * normally.
     *
     * = Return Values:
     * -1 : Operation failed. (can get only in POSIX).
     *  0 : All the operations were cancelled.
     *  1 : All the operations were already finished in this
     *	    handle. Unable to cancel them.
     *  2 : Atleast one of the requested operations cannot be
     *	    cancelled.
     * There is slight difference in the semantics between NT and POSIX
     * platforms which is given below.
     *
     * = Win32 :
     *	cancels all pending accepts operations that were issued by the
     *	calling thread.  The function does not cancel asynchronous
     *	operations issued by other threads.
     *	All I/O operations that are canceled will complete with the
     *	error ERROR_OPERATION_ABORTED.
     *
     * = POSIX:
     *  Attempts to cancel one or more asynchronous I/O requests
     *  currently outstanding against the {handle} registered in this
     *  operation.
     *  For requested operations that are successfully canceled, the
     *  associated  error  status is set to ECANCELED.
     */
    int cancel (void);

    // Return the underlying proactor.
    Proactor* proactor (void) const;

    // Destructor.
    virtual ~AsynchOpt ();
protected:
    // Constructor.
    AsynchOpt ();

    // Return the underlying implementation class.
    virtual AsynchOptImpl* implementation (void) const = 0;
};
// ------------------------------------------------------------------------
class AsynchReadStreamImpl;
class AsynchReadStreamResultImpl;
/**
 * @class AsynchReadStream
 *
 * Once {open} is called, multiple asynchronous {read}s can
 * started using this class.  An AsynchReadStream::Result
 * will be passed back to the {handler} when the asynchronous
 * reads completes through the {AsynchHandler::handle_read_stream}
 * callback.
 */
class AsynchReadStream : public AsynchOpt
{
public:
    // A do nothing constructor.
    AsynchReadStream ();

    // Destructor
    virtual ~AsynchReadStream ();

    /**
     * Initializes the factory with information which will be used with
     * each asynchronous call.
     *
     * @arg handler The AsynchHandler that will be called to handle completions
     *		    for operations initiated using this factory.
     * @arg handle  The handle that future read operations will use.
     *		    If <handle> == NDK_INVALID_HANDLE,
     *		    AsynchHandler::handle() will be called on <handler>
     *		    to get the correct handle.
     *
     * @retval 0    for success.
     * @retval -1   for failure; consult @c errno for further information.
     */
    int open (const AsynchHandler *handler,
	    NDK_HANDLE handle = NDK_INVALID_HANDLE,
	    const void *completion_key = 0,
	    Proactor *proactor = 0);

    /**
     * Initiate an asynchronous read operation.
     *
     * @arg message_block       The MessageBlock to receive the data.
     *				Received bytes will be placed in the block
     *				beginning at its current write pointer.
     *				If data is read, the message block's write
     *				pointer will be advanced by the number of
     *				bytes read.
     * @arg num_bytes_to_read   The maximum number of bytes to read.
     */
    int read (MessageBlock *message_block, size_t num_bytes_to_read);

    // Return the underlying implementation class.
    virtual AsynchOptImpl *implementation (void) const;
protected:
    // Implementation class that all methods will be forwarded to.
    AsynchReadStreamImpl *implementation_;
public:
    /**
     * @class Result
     *
     * @brief This is the class which will be passed back to the
     * {handler} when the asynchronous read completes. This class
     * forwards all the methods to the implementation classes.
     *
     * This class has all the information necessary for the
     * {handler} to uniquiely identify the completion of the
     * asynchronous read.
     */
    class Result : public AsynchResult
    {
	friend class EpollAsynchReadStreamResult;
    public:
	// The number of bytes which were requested at the start of the
	// asynchronous read.
	size_t bytes_to_read (void) const;

	// Message block which contains the read data.
	MessageBlock *message_block (void) const;

	// I/O handle used for reading.
	NDK_HANDLE handle (void) const;

	// Get the implementation class.
	AsynchReadStreamResultImpl *implementation (void) const;

    protected:
	// Constructor.
	Result (AsynchReadStreamResultImpl *implementation);

	// Destructor.
	virtual ~Result (void);

	// The implementation class.
	AsynchReadStreamResultImpl *implementation_;
    };
};
// ------------------------------------------------------------------------
class AsynchWriteStreamImpl;
class AsynchWriteStreamResultImpl;
/**
 * @class AsynchWriteStream
 *
 * Once {open} is called, multiple asynchronous {read}s can
 * started using this class.  An AsynchWriteStream::Result
 * will be passed back to the {handler} when the asynchronous
 * reads completes through the {AsynchHandler::handle_write_stream}
 * callback.
 */
class AsynchWriteStream : public AsynchOpt
{
public:
    // A do nothing constructor.
    AsynchWriteStream ();

    // Destructor
    virtual ~AsynchWriteStream ();

    /**
     * Initializes the factory with information which will be used with
     * each asynchronous call.
     *
     * @arg handler The AsynchHandler that will be called to handle completions
     *		    for operations initiated using this factory.
     * @arg handle  The handle that future read operations will use.
     *		    If <handle> == NDK_INVALID_HANDLE,
     *		    AsynchHandler::handle() will be called on <handler>
     *		    to get the correct handle.
     *
     * @retval 0    for success.
     * @retval -1   for failure; consult @c errno for further information.
     */
    int open (const AsynchHandler *handler,
	    NDK_HANDLE handle = NDK_INVALID_HANDLE,
	    const void *completion_key = 0,
	    Proactor *proactor = 0);

    /**
     * This starts off an asynchronous write.  Upto {bytes_to_write}
     * will be written from the {message_block}. Upon successful completion
     * of the write operation, {message_block}'s {rd_ptr} is updated to
     * reflect the data that was written. 
     */
    int write (MessageBlock *message_block, size_t num_bytes_to_read);

    // Return the underlying implementation class.
    virtual AsynchOptImpl *implementation (void) const;
protected:
    // Implementation class that all methods will be forwarded to.
    AsynchWriteStreamImpl *implementation_;
public:
    /**
     * @class Result
     *
     * @brief This is the class which will be passed back to the
     * {handler} when the asynchronous write completes. This class
     * forwards all the methods to the implementation classes.
     *
     * This class has all the information necessary for the
     * {handler} to uniquiely identify the completion of the
     * asynchronous write.
     */
    class Result : public AsynchResult
    {
	friend class EpollAsynchWriteStreamResult;
    public:
	// The number of bytes which were requested at the start of the
	// asynchronous write.
	size_t bytes_to_write (void) const;

	// Message block which contains the data to be written.
	MessageBlock *message_block (void) const;

	// I/O handle used for reading.
	NDK_HANDLE handle (void) const;

	// Get the implementation class.
	AsynchWriteStreamResultImpl *implementation (void) const;

    protected:
	// Constructor.
	Result (AsynchWriteStreamResultImpl *implementation);

	// Destructor.
	virtual ~Result (void);

	// The implementation class.
	AsynchWriteStreamResultImpl *implementation_;
    };
};
// ------------------------------------------------------------------------
class AsynchAcceptImpl;
class AsynchAcceptResultImpl;

/** 
 * @class ConnectionInfo
 */
struct ConnectionInfo
{
    ConnectionInfo (InetAddr &addr, NDK_HANDLE h)
    : accept_handle (h)
    , remote_address (addr)
    {}

    //
    ConnectionInfo ()
    : accept_handle (NDK_INVALID_HANDLE)
    , remote_address ()
    {}

    NDK_HANDLE accept_handle;

    InetAddr remote_address;
};
/**
 * @class AsynchAccept
 *
 * Once {open} is called, multiple asynchronous {read}s can
 * started using this class.  An AsynchAccept::Result
 * will be passed back to the {handler} when the asynchronous
 * reads completes through the {AsynchHandler::handle_accept}
 * callback.
 */
class AsynchAccept : public AsynchOpt
{
public:
    // A do nothing constructor.
    AsynchAccept ();

    // Destructor
    virtual ~AsynchAccept ();

    /**
     * Initializes the factory with information which will be used with
     * each asynchronous call. If ({handle} == NDK_INVALID_HANDLE),
     * {AsynchHandler::handle} will be called on the {handler} to get the
     * correct handle.
     */
    int open (const AsynchHandler *handler,
	    NDK_HANDLE handle = NDK_INVALID_HANDLE,
	    const void *completion_key = 0,
	    Proactor *proactor = 0);

    /**
     * This starts off an asynchronous read. Upto <num_to_accept> of 
     * connections will be accepted and stored in the ConnectionInfo 
     * that be stored in the <message_block> or occur error.  So the 
     * space of the message_block is must equal or large than 
     * <num_to_accept> times size of ConnectionInfo.
     */
    int accept (MessageBlock *message_block,
	    size_t num_to_accept);

    // Return the underlying implementation class.
    virtual AsynchOptImpl *implementation (void) const;
protected:
    // Implementation class that all methods will be forwarded to.
    AsynchAcceptImpl *implementation_;
public:
    /**
     * @class Result
     *
     * @brief This is the class which will be passed back to the
     * {handler} when the asynchronous write completes. This class
     * forwards all the methods to the implementation classes.
     *
     * This class has all the information necessary for the
     * {handler} to uniquiely identify the completion of the
     * asynchronous write.
     */
    class Result : public AsynchResult
    {
	friend class EpollAsynchAcceptResult;
    public:
	// The number of connection which were requested at the start of the
	// asynchronous accept.
	size_t num_to_accept (void) const;

	// Message block which contains the data to be written.
	MessageBlock *message_block (void) const;

	// I/O handle used for accepting new connections.
	NDK_HANDLE listen_handle (void) const;

	// I/O handle for the new connection.
	//NDK_HANDLE accept_handle (void) const;

	// Get the implementation class.
	AsynchAcceptResultImpl *implementation (void) const;

    protected:
	// Constructor.
	Result (AsynchAcceptResultImpl *implementation);

	// Destructor.
	virtual ~Result (void);

	// The implementation class.
	AsynchAcceptResultImpl *implementation_;
    };
};
/**
 * @class AsynchHandler
 *
 * @brief This base class defines the interface for receiving the
 * results of asynchronous operations.
 *
 * Subclasses of this class will fill in appropriate methods.
 */
class AsynchHandler
{
public:
    enum
    {
        NULL_MASK	    = 0x00000000,

        READ_MASK	    = 0x00000001,

        WRITE_MASK	    = 0x00000002,

        ACCEPT_MASK	    = 0x00000004,

        CONNECT_MASK	= 0x00000008	
    };
    // A do nothing constructor.
    AsynchHandler ();

    // Set proactor to <p>
    AsynchHandler (Proactor *p);

    // Virtual destruction.
    virtual ~AsynchHandler ();

    // This method will be called by AsynchAcceptor.
    // return -1: AsynchAcceptor will call handle_close.
    virtual int open (NDK_HANDLE );

    // This method will be called when an asynchronous read completes on
    // a stream.
    // return -1: Proactor will remote this handle.
    // return  0: Proactor do nothing.
    virtual int handle_read_stream (const AsynchReadStream::Result &result);

    // This method will be called when an asynchronous write completes
    // on a stream.
    // return -1: Proactor will remote this handle.
    // return  0: Proactor do nothing.
    virtual int handle_write_stream (const AsynchWriteStream::Result &result);

    // This method will be called when an asynchronous read completes on
    // a file.
    //virtual void handle_read_file (const AsynchReadFile::Result &result);

    // This method will be called when an asynchronous write completes
    // a file
    //virtual void handle_write_file (const AsynchWriteFile::Result &result);

    // This method will be called when an asynchronous accept completes.
    // return -1: Proactor will remote this handle.
    // return  0: Proactor do nothing.
    virtual int handle_accept (const AsynchAccept::Result &result);

    // This method will be called when an asynchronous connect completes.
    //virtual void handle_connect (const AsynchConnect::Result &result);

    // This method will be called by Proactor when handle_* method return non-zero
    virtual int handle_close (const int mask);

    // Get the proactor associated with this handler.
    Proactor *proactor (void) const;

    // Set the proactor.
    void proactor (Proactor *p);

    // Get the I/O handle used by this {handler}. This method will be
    // called by the Asynch* classes when an NDK_INVALID_HANDLE is
    // passed to {open}.
    virtual NDK_HANDLE handle (void) const;

    // Set the NDK_HANDLE value for this Handler.
    virtual void handle (NDK_HANDLE);

    // If you want to get the address of the new connectin, you must reload
    // this method.
    virtual void remote_addr (const InetAddr &remote_addr);
protected:
    // The proactor associated with this handler.
    Proactor *proactor_;

    // The NDK_HANDLE in use with this handler.
    NDK_HANDLE    handle_;
};
#include "Post.h"
#endif

